

#include "..\Common\Main.h"
#include "..\Common\Vector3.h"
//#include "..\Common\Matrix3x3.h"
#include <stdio.h>
using namespace Engine;

#define		MAP_SIZE	  1024							// Size Of Our .RAW Height Map (NEW)
#define		STEP_SIZE	  16							// Width And Height Of Each Quad (NEW)
#define		HEIGHT_RATIO  1.5f							// Ratio That The Y Is Scaled According To The X And Z (NEW)

App app;

bool bRender = false;
BYTE g_HeightMap[MAP_SIZE*MAP_SIZE];					// Holds The Height Map Data (NEW)
float scaleValue = 0.15f;								// Scale Value For The Terrain (NEW)


void LoadRawFile(char *inFilename, int nSize,BYTE * pHeightMap)
{
	FILE *pFile = NULL;
	pFile = fopen(inFilename,"r");

	if(pFile == NULL)  return;

	fread(pHeightMap,1,nSize,pFile);

	int result = ferror(pFile);
	fclose(pFile);
}




LRESULT CALLBACK Engine::WndProc(	HWND	hWnd,UINT	uMsg,WPARAM	wParam,	LPARAM	lParam)			
{
	switch (uMsg)									// Check For Windows Messages
	{
		case WM_ACTIVATE:							// Watch For Window Activate Message
		{
			if (!HIWORD(wParam))					// Check Minimization State
			{
				app.mWindow->mActive = TRUE;						// Program Is Active
			}
			else
			{
				app.mWindow->mActive = FALSE;						// Program Is No Longer Active
			}
			return 0;								// Return To The Message Loop
		}

		case WM_SYSCOMMAND:							// Intercept System Commands
		{
			switch (wParam)							// Check System Calls
			{
				case SC_SCREENSAVE:					// Screensaver Trying To Start?
				case SC_MONITORPOWER:				// Monitor Trying To Enter Powersave?
				return 0;							// Prevent From Happening
			}
			break;									// Exit
		}

		case WM_CLOSE:								// Did We Receive A Close Message?
		{
			PostQuitMessage(0);						// Send A Quit Message
			return 0;								// Jump Back
		}

		case WM_KEYDOWN:							// Is A Key Being Held Down?
		{
			app.mKeys[wParam] = TRUE;					// If So, Mark It As TRUE
			return 0;								// Jump Back
		}

		case WM_KEYUP:								// Has A Key Been Released?
		{
			app.mKeys[wParam] = FALSE;					// If So, Mark It As FALSE
			return 0;								// Jump Back
		}

		case WM_SIZE:								// Resize The OpenGL Window
		{
			Engine::ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height
			return 0;								// Jump Back
		}
	}

	// Pass All Unhandled Messages To DefWindowProc
	return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

void InitGL()
{
	glShadeModel(GL_SMOOTH);							// Enable Smooth Shading
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				// Black Background
	glClearDepth(1.0f);									// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations
	LoadRawFile("..\\Data\\Terrain.raw", MAP_SIZE * MAP_SIZE,g_HeightMap);
	//return TRUE;		
}

int Height(BYTE* pHeightMap,int X, int Y)
{
	int x = X %MAP_SIZE;
	int y = Y % MAP_SIZE;

	if(!pHeightMap) return 0;

	return pHeightMap[x+ (y* MAP_SIZE)];
}

void SetVertexColor(BYTE *pHeightMap, int x, int y)		// Sets The Color Value For A Particular Index, Depending On The Height Index
{
	if(!pHeightMap) return;								// Make Sure Our Height Data Is Valid

	float fColor = -0.15f + (Height(pHeightMap, x, y ) / 256.0f);

	// Assign This Blue Shade To The Current Vertex
	glColor3f(0, 0, fColor );
}

void RenderHeightMap(BYTE pHeightMap[])					// This Renders The Height Map As Quads
{
	int X = 0, Y = 0;									// Create Some Variables To Walk The Array With.
	int x, y, z;										// Create Some Variables For Readability

	if(!pHeightMap) return;								// Make Sure Our Height Data Is Valid

	if(bRender)											// What We Want To Render
		glBegin( GL_QUADS );							// Render Polygons
	else 
		glBegin( GL_LINES );							// Render Lines Instead

	for ( X = 0; X < MAP_SIZE; X += STEP_SIZE )
		for ( Y = 0; Y < MAP_SIZE; Y += STEP_SIZE )
		{
			// Get The (X, Y, Z) Value For The Bottom Left Vertex
			x = X;							
			y = Height(pHeightMap, X, Y );	
			z = Y;							

			// Set The Color Value Of The Current Vertex
			SetVertexColor(pHeightMap, x, z);

			glVertex3f(x, y, z);						// Send This Vertex To OpenGL To Be Rendered (Integer Points Are Faster)

			// Get The (X, Y, Z) Value For The Top Left Vertex
			x = X;										
			y = Height(pHeightMap, X, Y + STEP_SIZE );  
			z = Y + STEP_SIZE ;							
			
			// Set The Color Value Of The Current Vertex
			SetVertexColor(pHeightMap, x, z);

			glVertex3i(x, y, z);						// Send This Vertex To OpenGL To Be Rendered

			// Get The (X, Y, Z) Value For The Top Right Vertex
			x = X + STEP_SIZE; 
			y = Height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE ); 
			z = Y + STEP_SIZE ;

			// Set The Color Value Of The Current Vertex
			SetVertexColor(pHeightMap, x, z);
			
			glVertex3i(x, y, z);						// Send This Vertex To OpenGL To Be Rendered

			// Get The (X, Y, Z) Value For The Bottom Right Vertex
			x = X + STEP_SIZE; 
			y = Height(pHeightMap, X + STEP_SIZE, Y ); 
			z = Y;

			// Set The Color Value Of The Current Vertex
			SetVertexColor(pHeightMap, x, z);

			glVertex3f(x, y, z);						// Send This Vertex To OpenGL To Be Rendered
		}
	glEnd();

	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);					// Reset The Color
}

int DrawGLScene(GLvoid)									// Here's Where We Do All The Drawing
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear Screen And Depth Buffer
	glLoadIdentity();									// Reset The Current Modelview Matrix
	gluLookAt(212, 60, 194,  186, 55, 171,  0, 1, 0);	// This Determines Where The Camera's Position And View Is
	glScalef(scaleValue, scaleValue * HEIGHT_RATIO, scaleValue);
	RenderHeightMap(g_HeightMap);
	return TRUE;										// Keep Going
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	MSG msg;
	BOOL done = FALSE;

	app.Initialize(hInstance);

	Engine::CreateGLWindow(hInstance, app);
	ReSizeGLScene(app.mWindow->mWindowRect->right, app.mWindow->mWindowRect->bottom);
	InitGL();

	while(!done)
	{
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if(msg.message == WM_QUIT)
			{
				done  = TRUE;
			}
			else
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}else										// If There Are No Messages
		{
			DrawGLScene();
			// Draw The Scene.  Watch For ESC Key And Quit Messages From DrawGLScene()
			if (/*(app.mWindow->mActive && !DrawGLScene()) ||*/ app.mKeys[VK_ESCAPE])	// Active?  Was There A Quit Received?
			{
				done=TRUE;							// ESC or DrawGLScene Signalled A Quit
			}
			else									// Not Time To Quit, Update Screen
			{
				SwapBuffers(app.mWindow->mHdc);					// Swap Buffers (Double Buffering)
			}
		}
	}

	//KillGLWindow(hInstance, fullscreen, hRC,hDC,hWnd);
	KillGLWindow(app);
	return msg.wParam;
}
